package com.weighing.system.service.impl.server;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.weighing.common.annotation.DataSource;
import com.weighing.common.enums.DataSourceType;
import com.weighing.common.utils.StringUtils;
import com.weighing.system.domain.server.ProduceOrder;
import com.weighing.system.domain.server.ProduceOrderDetail;
import com.weighing.system.domain.server.WeighingDetail;
import com.weighing.system.domain.server.WeighingMaster;
import com.weighing.system.mapper.server.ProduceOrderMapper;
import com.weighing.system.mapper.server.WeighingMasterMapper;
import com.weighing.system.service.server.ProduceOrderService;
import com.weighing.system.utils.SerialNumberUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 工单主表 Service 实现类
 */
@Service
@Transactional
@DataSource(value = DataSourceType.SLAVE)
public class ProduceOrderServiceImpl extends ServiceImpl<ProduceOrderMapper, ProduceOrder>
        implements ProduceOrderService {

    @Resource
    private WeighingMasterMapper weighingMasterMapper;

    @Override
    public List<ProduceOrder> listAllWithDetails() {
        return baseMapper.selectAllWithDetails();
    }

    @Override
    public ProduceOrder getByBillNo(String billNo) {
        ProduceOrder produceOrder = baseMapper.selectByBillNo(billNo);
        if (produceOrder == null) {
            throw new RuntimeException("未找到对应工单号：" + billNo);
        }
        if (produceOrder.getCurrentState() != null && produceOrder.getCurrentState().contains("4")) {
            throw new RuntimeException("工单已结案");
        }
        produceOrder.setWeighingMasterListFinished(weighingMasterMapper.selectByFromBillNoFinished(billNo));
        assembleWeighingMaster(produceOrder);
        List<WeighingDetail> weighingDetailList = produceOrder.getWeighingDetailList();

        if (weighingDetailList != null && !weighingDetailList.isEmpty()) {
            Map<String, List<WeighingDetail>> weighingDetailMap = weighingDetailList.stream().collect(Collectors.groupingBy(WeighingDetail::getCuMaterialId));
            for (ProduceOrderDetail produceOrderDetail : produceOrder.getDetails()) {
                String thisBillNo = produceOrder.getWeighingMasterList().get(0).getBillNo();
                List<WeighingDetail> weighingDetails = weighingDetailMap.get(produceOrderDetail.getSubMaterialId());
                // 已生成单据号再进行填充
                if (weighingDetails != null) {
                    List<WeighingDetail> collect = weighingDetails.stream()
                            .filter(res -> res.getBillNo().equals(thisBillNo))
                            .sorted(Comparator.comparing(WeighingDetail::getRowNo).reversed())
                            .collect(Collectors.toList());
                    if (!collect.isEmpty()) {
                        produceOrderDetail.setWeighingDetailList(collect);
                    }
                }
                // 计算每个辅料的区间
                if (!produceOrderDetail.getIsMainMaterial() && produceOrderDetail.getMaterialType() != null && produceOrder.getWeighingMasterList().get(0).getBillNo() != null) {
                    List<WeighingDetail> details = produceOrder.getWeighingMasterList().get(0).getDetails();
                    for (WeighingDetail detail : details) {
                        detail.setProduceOrderDetail(produceOrder.getDetails().stream().filter(res -> res.getSubMaterialId().equals(detail.getCuMaterialId())).collect(Collectors.toList()).get(0));
                    }
                    if (produceOrderDetail.getMaterialType() == null || StringUtils.isEmpty(produceOrderDetail.getMaterialType())) {
                        continue;
                    }
                    String materialType = produceOrderDetail.getMaterialType().substring(0, 1);
                    List<WeighingDetail> result = new ArrayList<>(details.stream()
                            .collect(Collectors.toMap(
                                    WeighingDetail::getCuMaterialId,
                                    Function.identity(),
                                    (oldValue, newValue) -> {
                                        // 比较时间戳大小
                                        return oldValue.getCreateTime() > newValue.getCreateTime() ? oldValue : newValue;
                                    }
                            ))
                            .values());
                    List<WeighingDetail> filteredList = result.stream()
                            .filter(res -> res.getProduceOrderDetail() != null)
                            .filter(res -> res.getProduceOrderDetail().getMaterialType() != null)
                            .filter(res -> res.getProduceOrderDetail().getMaterialType().startsWith(materialType))
                            .filter(res -> Boolean.TRUE.equals(res.getProduceOrderDetail().getIsMainMaterial()))
                            .collect(Collectors.toList());
                    WeighingDetail w = null;
                    if (!filteredList.isEmpty()) {
                        w = filteredList.get(0);
                    } else {
                        // 处理未找到的情况
                        continue;
                    }                    // 比例
                    BigDecimal bl = produceOrderDetail.getBl();
                    // 浮动
                    BigDecimal flu = produceOrderDetail.getFlu() == null ? BigDecimal.ZERO : produceOrderDetail.getFlu();
                    BigDecimal quantity = w.getCumulativeQuantity().multiply(bl.multiply(new BigDecimal("0.01")));
                    BigDecimal upper = quantity.add(flu).setScale(3, RoundingMode.HALF_UP);
                    BigDecimal lower = quantity.subtract(flu).setScale(3, RoundingMode.HALF_UP);
                    produceOrderDetail.setUpper(upper.toString());
                    produceOrderDetail.setLower(lower.toString());
                }
            }
        }
        return produceOrder;
    }

    private void assembleWeighingMaster(ProduceOrder produceOrder) {
        if (produceOrder.getWeighingMasterList() == null || produceOrder.getWeighingMasterList().isEmpty()) {
            WeighingMaster weighingMaster = new WeighingMaster();
            weighingMaster.setFromBillNo(produceOrder.getBillNo());
            weighingMaster.setTypeId("0005");
            weighingMaster.setBillDate(SerialNumberUtil.generateSerialNumberLongSub8());
            List<WeighingMaster> weighingMasters = Collections.singletonList(weighingMaster);
            produceOrder.setWeighingMasterList(weighingMasters);
        }
        List<WeighingDetail> weighingDetailList = produceOrder.getWeighingDetailList();
        Map<String, List<WeighingDetail>> map = weighingDetailList.stream().collect(Collectors.groupingBy(WeighingDetail::getCuMaterialId));
        for (ProduceOrderDetail detail : produceOrder.getDetails()) {
            List<WeighingDetail> weighingDetails = map.get(detail.getSubMaterialId());
            if (weighingDetails != null && !weighingDetails.isEmpty() && detail.getWeighingDetailList() == null) {
                WeighingDetail w = weighingDetails.stream().sorted(Comparator.comparing(WeighingDetail::getCuTotalQuantity).reversed()).collect(Collectors.toList()).get(0);
                BigDecimal cuTotalQuantity = w.getCuTotalQuantity();
                WeighingDetail build = WeighingDetail.builder()
                        .cuTotalQuantity(cuTotalQuantity)
                        .cuMaterialId(w.getCuMaterialId())
                        .cuQuantity(BigDecimal.ZERO)
                        .build();
                detail.setWeighingDetailList(Collections.singletonList(build));
            }
        }
    }
}
